package com.yztstudy.Service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yztstudy.Mapper.OrderMapper;
import com.yztstudy.Service.OrderService;
import com.yztstudy.clients.ProductFeignClient;
import com.yztstudy.entity.Order;
import com.yztstudy.entity.Product;
import com.yztstudy.param.CartListParam;
import com.yztstudy.param.OrderParam;
import com.yztstudy.param.PageParam;
import com.yztstudy.param.ProductCollectParam;
import com.yztstudy.to.OrderToProduct;
import com.yztstudy.utils.R;
import com.yztstudy.vo.AdminOrderVo;
import com.yztstudy.vo.CartVo;
import com.yztstudy.vo.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private ProductFeignClient productFeignClient; // 商品的远程调用对象

    @Autowired
    private OrderMapper orderMapper;

    /**
     * TODO 保存订单
     * @param orderParam 前端发来的用户主键和多个商品
     * @return
     */
    @Transactional
    @Override
    public R save(OrderParam orderParam) {

        // TODO 1.准备数据
        List<Integer> cartIds = new ArrayList<>(); // 某个用户的所有购物车主键信息
        List<OrderToProduct> orderToProducts = new ArrayList<>(); // 发送给商品服务主键+数量信息
        List<Order> orderList = new ArrayList<>(); // 批量生成的订单

        // TODO 2.生成数据
        Integer userId = orderParam.getUserId(); // 用户主键
        Long orderId = System.currentTimeMillis(); // 商品主键

        for (CartVo cartVo : orderParam.getProducts())
        {
            cartIds.add(cartVo.getId());

            OrderToProduct orderToProduct = new OrderToProduct();
            orderToProduct.setNum(cartVo.getNum());
            orderToProduct.setProductId(cartVo.getProductID());
            orderToProducts.add(orderToProduct);

            Order order = new Order();
            order.setOrderId(orderId);
            order.setOrderTime(orderId);
            order.setUserId(userId);
            order.setProductId(cartVo.getProductID());
            order.setProductNum(cartVo.getNum());
            order.setProductPrice(cartVo.getPrice());
            orderList.add(order);
        }

        // TODO 3.订单数据批量保存
        saveBatch(orderList);

        // TODO 4.发送购物车服务消息
        rabbitTemplate.convertAndSend("topic.ex", "clear.cart", cartIds);

        // TODO 5.发送商品服务消息
        rabbitTemplate.convertAndSend("topic.ex", "sub.number", orderToProducts);
        return R.ok("下单成功!");
    }


    /**
     * TODO 分组查询购物车,展示订单
     * @param cartListParam 用户主键
     * @return
     */
    @Override
    public R list(CartListParam cartListParam) {

        // TODO 1.查询用户对应的全部订单项
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", cartListParam.getUserId());
        List<Order> orderList = baseMapper.selectList(wrapper); // 根据用户ID查询所有的订单

        // TODO 2.分组
        Map<Long, List<Order>> orderMap = orderList.stream().collect(Collectors.groupingBy(Order::getOrderId)); // 相同orderId的为一组

        // TODO 3.查询商品数据
        List<Integer> productIds = orderList.stream().map(Order::getProductId).collect(Collectors.toList()); // 获取商品ID集合

        ProductCollectParam productCollectParam = new ProductCollectParam();
        productCollectParam.setProductIds(productIds);

        List<Product> products = productFeignClient.cartList(productCollectParam); // 根据商品ID集合，获取商品集合
        Map<Integer, Product> productMap = products.stream().collect(Collectors.toMap(Product::getProductId, v -> v)); // 转换为map集合

        // TODO 4.结果封装
        List<List<OrderVo>> result = new ArrayList<>();
        for (List<Order> orders : orderMap.values()) // 遍历所有的组
        {
            List<OrderVo> orderVos = new ArrayList<>();
            for (Order order : orders) { // 遍历每一个组内的集合
                OrderVo orderVo = new OrderVo();
                BeanUtils.copyProperties(order, orderVo);
                Product product = productMap.get(order.getProductId());
                orderVo.setProductName(product.getProductName());
                orderVo.setProductPicture(product.getProductPicture());
                orderVos.add(orderVo);
            }
            result.add(orderVos);
        }

        log.info("OrderServiceImpl.list业务结束, 结果:{}", "订单展示成功!");
        return R.ok("订单展示成功!", result);
    }


    /**
     * TODO 检查订单里面是否有要删除的商品
     * @param productId 要删除的商品Id
     * @return
     */
    @Override
    public R check(Integer productId) {

        // TODO 1.构造查询条件
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("product_id", productId);
        Long count = baseMapper.selectCount(wrapper);

        // TODO 2.判断
        if (count == 0L)
        {
            return R.ok("订单中不存在要删除的商品!");
        }
        else {
            return R.fail("订单中存在要删除的商品");
        }
    }


    /**
     * TODO 分页查询订单
     * @param pageParam 分页参数
     * @return
     */
    @Override
    public R adminList(PageParam pageParam) {

        // TODO 1.分页参数计算完毕
        int offset = (pageParam.getCurrentPage() - 1) * pageParam.getPageSize(); // 偏移量
        int pageSize = pageParam.getPageSize(); // 每一页的大小

        // TODO 2.查询
        List<AdminOrderVo> adminOrderVos = orderMapper.selectAdminOrder(offset, pageSize);
        log.info("OrderServiceImpl.adminList方法执行完毕,结果为:{}", "订单数据查询成功!");
        return R.ok("订单数据查询成功!", adminOrderVos);
    }
}
